/**
 * 
 */
package group.anglers.bpmn.core.service.impls;

import group.anglers.bpmn.core.local.enums.ProcessState;
import group.anglers.bpmn.core.local.model.mappings.ProcessInstance;
import group.anglers.bpmn.core.local.models.ProcessContent;
import group.anglers.bpmn.core.local.models.ProcessPK;
import group.anglers.bpmn.core.local.services.Counter;
import group.anglers.bpmn.core.local.services.ProcessLocalService;
import group.anglers.om.core.custom.sql.utils.CustomSQLUtil;
import group.anglers.om.core.exceptions.OmException;
import group.anglers.om.core.persistence.Persistence;
import group.anglers.om.core.persistence.Query;

import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import javax.ejb.Stateless;
import javax.inject.Inject;

/**
 * @author an.pham
 * 
 */
@Stateless
public class PocessLocalServiceImpl implements ProcessLocalService {
	private static final Logger logger = Logger.getLogger(PocessLocalServiceImpl.class.getName());
	
	@Inject
	private Persistence persistence;
	
	@Inject
	private Counter counterUtils;

	@Override
	public long deploy(String processId, String name, Double version, String packageName, String content) throws OmException {
		try{
			try{
				persistence.startTransaction();
				
				Query<ProcessInstance> query = persistence.createQuery(
						CustomSQLUtil.get(ProcessInstance.class.getName() + ".findBy_ProcessID_PACKAGE_STATE")
						, ProcessInstance.class);
				
				query.setParameter(processId);
				query.setParameter(packageName);
				query.setParameter(ProcessState.LATEST.toString());
				// check if the processId and processPackage are already existed
				ProcessInstance processInstance = query.getSingleResult();
				/* if not found, it means that this is the first time of deployment */
				if(processInstance == null){
					processInstance = new ProcessInstance();
					processInstance.setInstanceId(counterUtils.generate());
					processInstance.setProcessId(processId);
					processInstance.setPackageName(packageName);
					processInstance.setContent(content);
					processInstance.setName(name);
					processInstance.setCreatedDate(new Date());
					processInstance.setVersion(version);
					processInstance.setState(ProcessState.LATEST.toString());
					// add a new process
					persistence.insert(processInstance);
					
					logger.info("The processId: " + processId + " has been added successfully !!!");
				}
				/* if found, let's compare the version between the aged one and the new one */
				else {
					logger.warning("The processId: " + processId + " is already existed. Comparing the version ... ");
					/* if the version of the new on is higher */
					if(processInstance.getVersion() < version){
						// turn the state of the aged one
						processInstance.setState(ProcessState.AGED.toString());
						// update the existing
						persistence.update(processInstance);
						
						processInstance.setInstanceId(counterUtils.generate());
						processInstance.setState(ProcessState.LATEST.toString());
						processInstance.setVersion(version);
						processInstance.setContent(content);
						processInstance.setCreatedDate(new Date());
						processInstance.setName(name);
						// update a new process
						persistence.insert(processInstance);
						
						logger.warning("The processId: " + processId + " has been update successfully !!!");
					}
					/* if the version of the new on is slower */
					else{
						logger.warning("The exsting processId: " + processId + " version is higher, so keep the exsting !!!");
					}
				}
				
				persistence.commitTransaction();
				
				return processInstance.getInstanceId();
			} catch(OmException e){
				persistence.rollbackTransaction();
				
				throw e;
			} 
			finally {
				persistence.flush();
			}
		}catch(OmException e){
			throw e;
		}
	}

	@Override
	public List<ProcessContent> retrieveEnabled() throws OmException {
		try{
			try{
				Query<ProcessContent> query = persistence.createQuery(
						CustomSQLUtil.get(ProcessInstance.class.getName() + ".retrieveBy_NOT_IN_STATE")
						, ProcessContent.class);
				
				query.setParameter(ProcessState.DISABLED.toString());
				
				return query.getResultList();
			}
			finally {
				persistence.flush();
			}
		}catch(OmException e){
			throw e;
		}
	}

	@Override
	public List<ProcessInstance> retrieveAll() throws OmException {
		try{
			try{
				Query<ProcessInstance> query = persistence.createQuery(
						CustomSQLUtil.get(ProcessInstance.class.getName() + ".retrieve_PROCESSID_VERSION_NAME_PACKAGE_STATE")
						, ProcessInstance.class);
				
				return query.getResultList();
			}
			finally {
				persistence.flush();
			}
		}catch(OmException e){
			throw e;
		}
	}

	@Override
	public ProcessPK findLatestVersion(String processId, String packageName) throws OmException {
		try{
			try{
				Query<ProcessPK> query = persistence.createQuery(
						CustomSQLUtil.get(ProcessInstance.class.getName() + ".findLatestVersionBy_PROCESSID_PACKAGE")
						, ProcessPK.class);
				
				query.setParameter(processId);
				query.setParameter(packageName);
				
				return query.getSingleResult();
			}
			finally {
				persistence.flush();
			}
		}catch(OmException e){
			throw e;
		}
	}
}
